/**
  ******************************************************************************
  * @file           : communicate_task.h
  * @author         : Tessia
  * @brief          : None
  * @attention      : None
  * @date           : 2024/2/15
  ******************************************************************************
  */



#ifndef SENTRY_LEFT_GIMBAL_COMMUNICATE_TASK_H
#define SENTRY_LEFT_GIMBAL_COMMUNICATE_TASK_H

#include "CAN_bsp.h"
#include "drv_can_dr16.h"
#include "driver_vision.h"
#include "usart.h"
#include "usbd_cdc_if.h"
#include "vision_task.h"
#include "filtering_drv.h"


#define MATCH_DEBUG 1 //在彩虹楼场地

const uint16_t restorable_HP = 600;   //联盟赛可供恢复值

const float X_AXIS_OFFSET = 6.562;    //从哨兵坐标原点到官方坐标原点，加上该值
const float Y_AXIS_OFFSET = 5.350;    //从哨兵坐标原点到官方坐标原点，加上该值

enum game_stage{
    match_not_start = 0,
    ready_stage,
    self_check,
    countdown_stage,
    during_the_match,
    match_settlement
};



#pragma pack(1)
typedef struct {
    uint16_t ch0: 11;//keil中不兼容，待看
    uint16_t ch1: 11;
    uint16_t ch2: 11;
    uint16_t ch3: 11;
    uint8_t s1: 2;
    uint8_t s2: 2;
    uint8_t is_lost: 1;
    uint8_t reverse_0: 7;
    uint8_t reverse_1: 8;
} rc_info_tran;
#pragma pack()

#pragma pack(1)
typedef struct {
    float yaw_angle;
    uint8_t is_flip_over: 1;
    uint8_t reverse_0: 7;
    uint8_t reverse_1: 8;
    uint8_t reverse_2: 8;
    uint8_t reverse_3: 8;
} chassis_info_tran;
#pragma pack()

#pragma pack(1)
typedef struct {            //都使用朴素机器人坐标系,前x,左y,上z
    uint8_t frame_header;   //帧头 0x20
    float x_speed;          //x方向速度
    float y_speed;          //y方向速度
    uint8_t can_not_go;     //无法抵达
    float coo_x_current;    //当前x坐标
    float coo_y_current;    //当前y坐标
    float radar_yaw;        //雷达发送的大yaw，做补偿用
    uint8_t is_spin;        //是否开启旋转
    float coo_x_correction; //修正x坐标，该坐标为导航实际去往的坐标
    float coo_y_correction; //修正y坐标，该坐标为导航实际去往的坐标
    uint8_t is_attack_engineer; //是否击打工程
    uint8_t is_attack_outpost;  //是否开局击打前哨站
    uint8_t is_not_patrol;      //是否不前压
    uint8_t camera_0;           //小摄像头0号
    uint8_t camera_1;           //小摄像头1号
    uint8_t camera_2;           //小摄像头2号
    uint8_t camera_3;           //小摄像头3号
    uint32_t reserve_1: 8;
    uint32_t reserve_2: 32;
    uint32_t reserve_3: 32;
    uint32_t reserve_4: 32;
    uint32_t reserve_5: 32;
    uint32_t reserve_6: 32;
    uint32_t reserve_7: 32;
    uint8_t frame_tail;     //帧尾 0x21
} radar_info_tran;
#pragma pack()

typedef struct {
    float x_speed;
    float y_speed;
    uint8_t can_not_go;     //无法到达
    float coo_x_current;    //当前x坐标
    float coo_y_current;    //当前y坐标
    float radar_current_yaw;
    int32_t round_cnt;
    float radar_total_yaw;
    float radar_total_yaw_filtered;
    uint8_t is_spin;        //是否开启旋转
    float coo_x_correction; //修正x坐标，该坐标为导航实际去往的坐标
    float coo_y_correction; //修正y坐标，该坐标为导航实际去往的坐标
    uint8_t no_attack_engineer; //是否击打工程
    uint8_t is_attack_outpost;  //是否开局击打前哨站
    uint8_t is_not_patrol;      //是否不前压
    uint8_t camera_0;           //小摄像头0号
    uint8_t camera_1;           //小摄像头1号
    uint8_t camera_2;           //小摄像头2号
    uint8_t camera_3;           //小摄像头3号
} radar_info;


#pragma pack(1)
typedef struct {            //都使用朴素机器人坐标系,前x,左y,上z
    uint8_t frame_header;   //帧头 0x20
    float coo_x;            //x坐标
    float coo_y;            //y坐标
    uint8_t stop;           //停止
    uint8_t red1blue0;
    uint8_t sentry_state;
    uint8_t sentry_event;
    uint8_t constrained_defence_state;
    uint32_t reverse_1: 8;
    uint32_t reverse_2: 32;
    uint32_t reverse_3: 32;
    uint32_t reverse_4: 32;
    uint32_t reverse_5: 32;
    uint8_t frame_tail;     //帧尾 0x21
} coo_info_tran;
#pragma pack()

typedef struct {            //都使用朴素机器人坐标系,前x,左y,上z
    float coo_x;            //x坐标
    float coo_y;            //y坐标
    uint8_t stop;           //停止
} coo_info;

#pragma pack(1)
typedef struct {            //都使用朴素机器人坐标系,前x,左y,上z
    float speed_x;
    float speed_y;
} speed_info;
#pragma pack()


typedef struct {
    float yaw_angle;
    uint8_t is_flip_over;
} chassis_info;

#pragma pack(1)
typedef struct {
    uint16_t current_HP;                //当前血量
    uint16_t shooter_barrel_cooling_value;    //机器人枪口每秒冷却值
    /*game_progress
0 ：未开始比赛
1 ：准备阶段
2 ：自检阶段
3 ： 5s 倒计时
4 ：对战中
5 ：比赛结算中*/
    uint8_t  game_progress: 4;      //当前比赛阶段
    uint16_t stage_remain_time;     //当前阶段剩余时间，单位s
    /* bit 0-3 ：
      当血量变化类型为装甲伤害，代表装甲 ID ，
      其中数值为 0-4 号代表机器人的五个装甲片，
      其他血量变化类型，该变量数值为 0 */
    uint8_t be_hit: 1;              //是否受击
    uint8_t hurt_armor_id: 4;
    /*hurt_type
     *     bit 4-7 ：血量变化类型
     *     0x0 装甲伤害扣血
     *     0x1 模块掉线扣血
     *     0x2 超射速扣血
     *     0x3 超枪口热量扣血
     *     0x4 超底盘功率扣血
     *     0x5 装甲撞击扣血
     */
    uint8_t mains_power_shooter_output : 1;     //1 为有 24V 输出， 0 为无 24v 输出

    uint8_t is_occupy_patrol_zone: 1;      //是否占领巡逻区
    uint8_t is_occupy_healing_spot: 1;     //是否占领补血点

    uint8_t HP_deduction_reason: 4;
} judge_info_0_tran;
#pragma pack()


typedef struct {
    uint16_t last_HP;                   //上次血量
    uint16_t current_HP;                //当前血量
    uint16_t shooter_barrel_cooling_value;    //机器人枪口每秒冷却值
    uint8_t  game_progress;      //当前比赛阶段
    /*game_progress
0 ：未开始比赛
1 ：准备阶段
2 ：自检阶段
3 ： 5s 倒计时
4 ：对战中
5 ：比赛结算中*/
    uint16_t stage_remain_time;     //当前阶段剩余时间，单位s
    /* bit 0-3 ：
      当血量变化类型为装甲伤害，代表装甲 ID ，
      其中数值为 0-4 号代表机器人的五个装甲片，
      其他血量变化类型，该变量数值为 0 */
    uint8_t be_hit;              //是否受击
    uint8_t hurt_armor_id;
    /*hurt_type
     *     bit 4-7 ：血量变化类型
     *     0x0 装甲伤害扣血
     *     0x1 模块掉线扣血
     *     0x2 超射速扣血
     *     0x3 超枪口热量扣血
     *     0x4 超底盘功率扣血
     *     0x5 装甲撞击扣血
     */
    uint8_t mains_power_shooter_output;     //1 为有 24V 输出， 0 为无 24v 输出
    uint8_t HP_deduction_reason;

    uint8_t is_occupy_patrol_zone;      //是否占领巡逻区
    uint8_t is_occupy_healing_spot;     //是否占领补血点
} judge_info_0;

#pragma pack(1)
typedef struct {
    uint8_t is_blue: 1;
    uint16_t shooter_barrel_heat_limit;    //机器人1号枪口热量上限
    uint16_t maximum_HP;                   //血量上限

    /*game_type
1 ：RoboMaster 机甲大师赛
2 ：RoboMaster 机甲大师单项赛
3 ：ICRA RoboMaster 人工智能挑战赛
4 ：RoboMaster 联盟赛 3V3
5 ：RoboMaster 联盟赛 1V1*/
    uint8_t  game_type: 4;
    uint16_t remaining_gold_coin;          //剩余金币
    uint64_t reverse: 11;
} judge_info_1_tran;
#pragma pack()

#pragma pack(1)
typedef struct {
    uint16_t projectile_allowance_17mm;    //允许发弹量
    uint8_t shooter_id;  //发射机构ID
    float bullet_speed;  //弹丸初速度
    uint64_t reverse: 8;
} judge_info_2_tran;
#pragma pack()

typedef struct {
    uint16_t projectile_allowance_17mm;    //允许发弹量
    uint8_t shooter_id;  //发射机构ID
    float bullet_speed;  //弹丸初速度
} judge_info_2;

typedef struct {
    uint8_t is_blue;
    uint16_t shooter_barrel_heat_limit;    //机器人1号枪口热量上限
    uint16_t maximum_HP;                   //血量上限

    /*game_type
1 ：RoboMaster 机甲大师赛
2 ：RoboMaster 机甲大师单项赛
3 ：ICRA RoboMaster 人工智能挑战赛
4 ：RoboMaster 联盟赛 3V3
5 ：RoboMaster 联盟赛 1V1*/
    uint8_t  game_type;
    uint16_t remaining_gold_coin;          //剩余金币
} judge_info_1;


#pragma pack(1)
typedef struct {
    uint16_t shooter_17mm_1_barrel_heat; //第1个17mm发射机构的枪口热量
    uint16_t shooter_17mm_2_barrel_heat;
    uint32_t reverse;
} judge_info_3_tran;
#pragma pack()

typedef struct {
    uint16_t shooter_17mm_barrel_heat;
} judge_info_3;

#pragma pack(1)
typedef struct {
    uint16_t enemy_1_robot_HP;
    uint16_t enemy_2_robot_HP;
    uint16_t enemy_3_robot_HP;
    uint16_t enemy_4_robot_HP;
} judge_HP_info_0;
#pragma pack()

#pragma pack(1)
typedef struct {
    uint16_t enemy_5_robot_HP;
    uint16_t enemy_7_robot_HP;
    uint16_t enemy_outpost_HP;
    uint16_t enemy_base_HP;
} judge_HP_info_1;
#pragma pack()

#pragma pack(1)
typedef struct {
    uint16_t our_outpost_HP;
    uint16_t our_base_HP;
    uint64_t reserve: 32;
} judge_HP_info_2;
#pragma pack()

struct judge_HP_info{
    uint16_t enemy_1_robot_HP;
    uint16_t enemy_2_robot_HP;
    uint16_t enemy_3_robot_HP;
    uint16_t enemy_4_robot_HP;
    uint16_t enemy_5_robot_HP;
    uint16_t enemy_7_robot_HP;
    uint16_t enemy_outpost_HP;
    uint16_t enemy_base_HP;
    uint16_t our_outpost_HP;
    uint16_t our_base_HP;
};


#pragma pack(1)
typedef struct {
    float chassis_yaw_cal;   //计算出来发给底盘的yaw
    uint8_t is_target_detected: 1;
    uint8_t is_chassis_yaw_stop: 1;
    uint8_t is_spin: 1;
    uint8_t is_use_capacitor: 1;
    uint8_t high_speed_spin: 1;
    uint8_t high_speed_translation: 1;
    uint8_t slope_speed_translation: 1;
    uint64_t reserve: 25;
} armor_chassis_info;
#pragma pack()

#pragma pack(1)
typedef struct {
    float chassis_yaw_real;   //计算出来大yaw的值
    uint8_t is_confirm_revive: 1;                       //是否确认复活
    uint8_t is_exchange_immediate_revive: 1;            //是否兑换立即复活
    uint16_t exchange_ammo_amount: 11;                  //哨兵将要兑换的发弹量值，开局为0，修改此值后，哨兵在补血点即可兑换允许发弹量。
    uint8_t remote_exchange_ammo_request_count: 4;      //哨兵远程兑换发弹量的请求次数，开局为0，修改此值即可请求远程兑换发弹量。
    uint8_t remote_exchange_health_request_count: 4;    //哨兵远程兑换血量的请求次数，开局为0，修改此值即可请求远程兑换血量。
    uint32_t reserve: 11;                               //保留
} yaw_and_decision_info;
#pragma pack()

typedef struct {
    uint8_t is_confirm_revive;                      //是否确认复活
    uint8_t is_exchange_immediate_revive;           //是否兑换立即复活
    uint16_t exchange_ammo_amount;                  //哨兵将要兑换的发弹量值，开局为0，修改此值后，哨兵在补血点即可兑换允许发弹量。
    uint8_t remote_exchange_ammo_request_count;     //哨兵远程兑换发弹量的请求次数，开局为0，修改此值即可请求远程兑换发弹量。
    uint8_t remote_exchange_health_request_count;   //哨兵远程兑换血量的请求次数，开局为0，修改此值即可请求远程兑换血量。
} sentry_decision_info;

#pragma pack(1)
typedef struct {
    uint8_t frame_header;      //帧头 0x30
    uint8_t is_target_detected;//是否看见敌人
    uint8_t auto_aim;          //是否开启自瞄
    uint8_t is_left_of_axis;   //是否在中轴线左侧
    uint8_t go_attack_outpost; //击打前哨站标志位
    uint8_t is_radar_connect;  //是否与雷达建立通信
    uint8_t camera_0_data;     //小摄像头0的数据

    float twins_pitch;         //计算出来左头的需达到的pitch
    float twins_yaw;           //计算出来左头的需达到的yaw
    float radar_total_yaw;     //雷达yaw

    uint8_t hero_aim_permit;
    uint8_t engineer_aim_permit;
    uint8_t infantry_3_aim_permit;
    uint8_t infantry_4_aim_permit;
    uint8_t infantry_5_aim_permit;
    uint8_t sentry_aim_permit;
    uint8_t base_aim_permit;
    uint8_t outpost_aim_permit;

    uint8_t frame_tail;        //帧尾 0x31

} twins_tran_info;
#pragma pack()

#pragma pack(1)
typedef struct {
    uint8_t frame_header;         //帧头 0x30
    uint8_t is_target_detected;   //是否看见敌人
    uint8_t armor_number_last;    //最近一次装甲板编号
    uint8_t is_right_of_axis;     //是否在中轴线右侧
    uint8_t is_chassis_yaw_stop;  //大yaw停止转动，同时是视觉暂留标志位
    float twins_pitch;            //计算出来右头需达到的的pitch
    float twins_yaw;              //计算出来右头需达到的yaw
    float chassis_cal_yaw;        //左头计算出来底盘的yaw
    float current_left_yaw;       //左头当前yaw
    uint8_t frame_tail;           //帧尾 0x31

} twins_receive_info_tran;
#pragma pack()

typedef struct {
    uint8_t is_target_detected;
    uint8_t armor_number_last;            //最近一次装甲板编号
    uint8_t is_right_of_axis;
    uint8_t is_chassis_yaw_stop;          //大yaw停止转动，同时是视觉暂留标志位
    float twins_pitch;
    float twins_yaw;
    float chassis_cal_yaw;
    float current_left_yaw;               //左头当前yaw

} twins_receive_info;

#pragma pack(1)
typedef struct {
    uint8_t robot_number;
    uint8_t is_reliable;
    uint16_t x;
    uint16_t y;
    uint16_t reserve;
} enemy_coo_tran;
#pragma pack()

typedef struct {
    uint8_t is_reliable;        //是否可信
    float x;
    float y;
} enemy_robot_coo;

#pragma pack(1)
typedef struct {
    uint8_t sentry_state;
    uint8_t sentry_destination;
    uint8_t sentry_event;
    uint8_t reserve_0;
    uint32_t reserve_1;
} sentry_to_robot;
#pragma pack()


#pragma pack(1)
typedef struct {
    uint8_t cmd_keyboard;
    uint16_t position_x;
    uint16_t position_y;
    uint32_t reserve: 24;
} aerial_operator_data_tran;
#pragma pack()


typedef struct {
    uint8_t cmd_keyboard;
    float position_x;
    float position_y;
} aerial_operator_data;


enum match_type{
    RMUL = 0,   //高校联盟赛
    RMUC = 1,   //超级对抗赛
    debug = 2,
};

enum enemy_num{
    hero = 1,
    engineer = 2,
    infantry_3 = 3,
    infantry_4 = 4,
    infantry_5 = 5,
    sentry = 7,
    base = 10,          //基地
    outpost = 11,       //前哨站
};

#ifdef __cplusplus
extern "C" {
#endif
//C
void communicate_can_task(void *argument);
void communicate_uart_receive_task(void *argument);
void communicate_uart_vision_transmit_task(void *argument);
void communicate_usb_receive_task(void *argument);
void communicate_usb_transmit_task(void *argument);
void communicate_can_decision_task(void *argument);
void communicate_uart_twins_transmit_task(void *argument);
void communicate_chassis_yaw_task(void *argument);
void communicate_robot_interaction_task(void *argument);
#ifdef __cplusplus
}
#endif
//C++

#endif //SENTRY_LEFT_GIMBAL_COMMUNICATE_TASK_H
